﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace memcached
{
    /// <summary>
    /// NCache Express store provider.
    /// </summary>
    /// <remarks>Thread safe.</remarks>
    public class NCache : ICache, IDisposable
    {
        /// <summary>
        /// Initialize.
        /// </summary>
        /// <param name="id">ncache instance id</param>
        public NCache(string id)
        {
            c = Alachisoft.NCacheExpress.Web.Caching.NCache.InitializeCache(id);
            c.ExceptionsEnabled = true;
        }

        /// <summary></summary>
        public NCache()
            : this("ncache")
        {
        }

        private Alachisoft.NCacheExpress.Web.Caching.Cache c;

        /// <summary></summary>
        public bool Remove(string key)
        {
            object currentValue = c.Remove(key);
            return true;
        }

        /// <summary></summary>
        public bool Set(string key, object value)
        {
            try
            {
                c.Insert(
                    key,
                    value,
                    null,
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoAbsoluteExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoSlidingExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.CacheItemPriority.NotRemovable);
                return true;
            }
            catch (Alachisoft.NCacheExpress.Runtime.Exceptions.OperationFailedException e)
            {
                System.Diagnostics.Trace.TraceError(e.Message);
                return false;
            }
        }

        /// <summary></summary>
        public bool Set(string key, int validFor, object value)
        {
            try
            {
                c.Insert(
                    key,
                    value,
                    null,
                    DateTime.Now.AddSeconds(validFor),
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoSlidingExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.CacheItemPriority.Default);
                return true;
            }
            catch (Alachisoft.NCacheExpress.Runtime.Exceptions.OperationFailedException e)
            {
                System.Diagnostics.Trace.TraceError(e.Message);
                return false;
            }
        }

        /// <summary></summary>
        public bool Set(string key, DateTime expireAt, object value)
        {
            try
            {
                c.Insert(
                    key,
                    value,
                    null,
                    expireAt,
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoSlidingExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.CacheItemPriority.Default);
                return true;
            }
            catch (Alachisoft.NCacheExpress.Runtime.Exceptions.OperationFailedException e)
            {
                System.Diagnostics.Trace.TraceError(e.Message);
                return false;
            }
        }

        /// <summary></summary>
        public bool Add(string key, int validFor, object value)
        {
            try
            {
                object res = c.Add(
                    key,
                    value,
                    null,
                    DateTime.Now.AddSeconds(validFor),
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoSlidingExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.CacheItemPriority.Default);
                return true;
            }
            catch (Alachisoft.NCacheExpress.Runtime.Exceptions.OperationFailedException e)
            {
                System.Diagnostics.Trace.TraceError(e.Message);
                return false;// key already exists
            }
        }

        /// <summary></summary>
        public bool Add(string key, DateTime expireAt, object value)
        {
            try
            {
                object res = c.Add(
                    key,
                    value,
                    null,
                    expireAt,
                    Alachisoft.NCacheExpress.Web.Caching.Cache.NoSlidingExpiration,
                    Alachisoft.NCacheExpress.Web.Caching.CacheItemPriority.Default);
                return true;
            }
            catch (Alachisoft.NCacheExpress.Runtime.Exceptions.OperationFailedException e)
            {
                System.Diagnostics.Trace.TraceError(e.Message);
                return false;// key already exists
            }
        }

        /// <summary></summary>
        public T Get<T>(string key, out bool success)
        {
            object value = c.Get(key);
            success = true;
            if (value != null && value is T)
                return (T)value;
            return default(T);
        }

        /// <summary></summary>
        public object Get(string key, out bool success)
        {
            object value = c.Get(key);
            success = true;
            return value;
        }

        /// <summary></summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            if (c != null)
            {
                c.Dispose();
                c = null;
            }
        }
    }
}